#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#include <string.h>
#include <unistd.h>

#define TAMBUFFER 65536
double timeval_diff(struct timeval *a, struct timeval *b);

int main(int argc, char* argv[])
{
    int file_descriptor_origen, file_descriptor_destino;
    int i;
    struct timeval tiempo_inicio, tiempo_final;
    double tiempo_transcurrido[17];
    char nombre_fichero_destino[30];
    char buffer[TAMBUFFER];
    int numeros[17] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536};
    int num_bytes;

    if (argc != 2)
    {
        printf("Error en el número de parámetros\n");
        exit(-1);
    }

    if((file_descriptor_origen = open(argv[1],0666)) == -1)
    {
        close(file_descriptor_origen);
        printf("Error de apertura del fichero.\n");
        exit(-1);
    }

    /* Crear fichero destino */
    for (i = 0; i <17; i++)
    {
        /* Crear el fichero destino */
        sprintf(nombre_fichero_destino,"nom_fich.%d",numeros[i]);
        printf("Estoy trabajando con el fichero => %s\n",nombre_fichero_destino);
        if ((file_descriptor_destino=open(nombre_fichero_destino,O_CREAT|O_TRUNC|O_WRONLY,644)) < 0)
        {
            close(file_descriptor_destino);
            printf("Error de apertura del fichero nom_fich.%d\n",numeros[i]);
            exit(-1);
        }
        /* Calcular el tiempo en este punto */
        gettimeofday(&tiempo_inicio,NULL);
        /* Copiar el cotenido del fichero 1 al fichero 2 */
        /* Lectura */
        while((num_bytes = read(file_descriptor_origen,buffer,numeros[i]))!=0)
        {
            if(write(file_descriptor_destino,buffer,numeros[i]) < 0)
            {
                close(file_descriptor_destino);
                printf("Error de escritura en el archivo %s",nombre_fichero_destino);
                exit(-1);
            }
        }

        /* Volver al comienzo del archivo origen */
        lseek(file_descriptor_origen,0,SEEK_SET);

        gettimeofday(&tiempo_final,NULL);
        /* Calcular el tiempo transcurrido */
        tiempo_transcurrido[i] = timeval_diff(&tiempo_final, &tiempo_inicio);
    }
    close(file_descriptor_destino);

    close(file_descriptor_origen);
    /* Mostrar el rendimiento de todos los copiados */
    printf("\n-----------------------------------------------\n");
    printf("----------------- Rendimiento -----------------\n");
    printf("-----------------------------------------------\n");
    for (i = 0; i < 17; i++)
    {
        printf("Tamaño buffer = %d  =>    %g us \n",numeros[i],tiempo_transcurrido[i]*1000000);
    }
    printf("-----------------------------------------------\n");


    return 0;
}

/* -------------------------------------------------- */
/* retorna "a - b" en segundos */
double timeval_diff(struct timeval *a, struct timeval *b)
{
  return
    (double)(a->tv_sec + (double)a->tv_usec/1000000) -
    (double)(b->tv_sec + (double)b->tv_usec/1000000);
}
